/**
 * Dispatches notifications of a right or middle click on the Flash Player to
 * the Flash application. The dispatcher also prevents the normal right-click
 * context menu from appearing if the Flash player instructs it to.
 *
 * @param flashPlayer a reference to the embedded Flash Player, or the ID of
 *               the element.
 */
function MouseEventDispatcher(flashPlayer) {
   /**
    * Breaks up the cycles between this <code>MouseEventDispatcher</code> and
    * the document so that the document can be garbage collected.
    */
   function cleanup() {
      flashPlayer = null;
   }

   /**
    * Prevents the context menu from appearing in Internet Explorer when
    * right-clicking on the Flash Player.
    */
   function handleContextMenuIE() {
      return window.event.srcElement != flashPlayer;
   }

   /**
    * In WebKit browsers and Gecko browsers, notifies the Flash Player the
    * right or middle mouse button was pressed.
    *
    * @param e the event object.
    */
   function handleMouseDown(e) {
      if (e.target == flashPlayer) {
         if (e.button == 1 && notifyMiddleMouseDown(e) ||
            e.button == 2 && notifyRightMouseDown(e)) {
            e.stopPropagation();
            e.preventDefault();
         }
      }
   }

   /**
    * In Internet Explorer, notifies the Flash Player that the right or middle
    * mouse button was pressed and redirects the event to the document.
    */
   function handleMouseDownIE() {
      if (window.event.button == 2 && notifyRightMouseDown(window.event) ||
         window.event.button == 4 && notifyMiddleMouseDown(window.event)) {
         document.body.setCapture();
      }
   }

   /**
    * In WebKit browsers and Gecko browsers, notifies the Flash Player that the
    * right or middle mouse button was released.
    *
    * @param e The event data.
    */
   function handleMouseUp(e) {
      if (e.target == flashPlayer) {
         if (e.button == 1) {
            notifyMiddleMouseUp(e);
         } else if (e.button == 2) {
            notifyRightMouseUp(e);
         }
      }
   }

   /**
    * Handles the release of the mouse button in Internet Explorer by ceasing
    * the redirection of mouse events to the document and notifying the Flash
    * Player.
    */
   function handleMouseUpIE() {
      if (window.event.button == 2) {
         document.body.releaseCapture();
         if (window.event.srcElement == flashPlayer) {
            notifyRightMouseUp(window.event);
         }
      } else if (window.event.button == 4) {
         document.body.releaseCapture();
         if (window.event.srcElement == flashPlayer) {
            notifyMiddleMouseUp(window.event);
         }
      }
   }

   /**
    * Initializes the dispatcher.
    */
   function initialize() {
      if (typeof(flashPlayer) == "string") {
         flashPlayer = document.getElementById(flashPlayer);
      }
      if (window.addEventListener) {
         window.addEventListener("mousedown", handleMouseDown, true);
         window.addEventListener("mouseup", handleMouseUp, true);
         window.addEventListener("unload", cleanup, false);
      } else {
         flashPlayer.attachEvent("onmousedown", handleMouseDownIE);
         document.body.attachEvent("onmouseup", handleMouseUpIE);
         document.body.attachEvent("oncontextmenu", handleContextMenuIE);
         window.attachEvent("onunload", cleanup);
      }
   }

   /**
    * Notifies the Flash Player that the middle mouse button was pressed down.
    *
    * @param e The event data.
    *
    * @return The response from the Flash Player.
    */
   function notifyMiddleMouseDown(e) {
      return flashPlayer.middleMouseDown(e.ctrlKey, e.altKey, e.shiftKey);
   }

   /**
    * Notifies the Flash Player that the middle mouse button was released.
    *
    * @param e The event data.
    *
    * @return The response from the Flash Player.
    */
   function notifyMiddleMouseUp(e) {
      return flashPlayer.middleMouseUp(e.ctrlKey, e.altKey, e.shiftKey);
   }

   /**
    * Notifies the Flash Player that the right mouse button was pressed down.
    *
    * @param e The event data.
    *
    * @return The response from the Flash Player.
    */
   function notifyRightMouseDown(e) {
      return flashPlayer.rightMouseDown(e.ctrlKey, e.altKey, e.shiftKey);
   }

   /**
    * Notifies the Flash Player that the right mouse button was released.
    *
    * @param e The event data.
    *
    * @return The response from the Flash Player.
    */
   function notifyRightMouseUp(e) {
      return flashPlayer.rightMouseUp(e.ctrlKey, e.altKey, e.shiftKey);
   }

   initialize();
}
